home *** CD-ROM | disk | FTP | other *** search
/ Apple Developer Connection Student Program / ADC Tools Sampler CD Disk 3 1999.iso / Metrowerks CodeWarrior / Java Support / Java_Source / Java2 / src / javax / swing / SwingGraphics.java < prev    next >
Encoding:
Java Source  |  1999-05-28  |  19.2 KB  |  661 lines  |  [TEXT/CWIE]

  1. /*
  2.  * @(#)SwingGraphics.java    1.25 98/08/31
  3.  *
  4.  * Copyright 1997, 1998 by Sun Microsystems, Inc.,
  5.  * 901 San Antonio Road, Palo Alto, California, 94303, U.S.A.
  6.  * All rights reserved.
  7.  *
  8.  * This software is the confidential and proprietary information
  9.  * of Sun Microsystems, Inc. ("Confidential Information").  You
  10.  * shall not disclose such Confidential Information and shall use
  11.  * it only in accordance with the terms of the license agreement
  12.  * you entered into with Sun.
  13.  */
  14. package javax.swing;
  15.  
  16. /**
  17.  * A private graphics to access clip bounds without creating a new
  18.  * rectangle
  19.  *
  20.  * @version 1.25 08/31/98
  21.  * @author Arnaud Weber
  22.  */
  23.  
  24. import java.awt.*;
  25. import java.awt.image.*;
  26. import java.util.Stack;
  27.  
  28.  
  29. import java.text.AttributedCharacterIterator;
  30.  
  31.  
  32. class SwingGraphics extends Graphics implements GraphicsWrapper {
  33.     Graphics graphics;
  34.     Graphics originalGraphics;
  35.     Rectangle clipRect;
  36.     Color currentColor;
  37.     Font currentFont;
  38.  
  39.     int translateX = 0;    // translation delta since initialization
  40.     int translateY = 0;
  41.  
  42.     /* The SwingGraphics this object was cloned from, if any. */
  43.     SwingGraphics previous;
  44.  
  45.     /* Can this context be restored to its original state? */
  46.     private boolean restorable = true;
  47.  
  48.     /* diagnostic aids -- should be false for production builds. */
  49.     private static final boolean trace = false;   // trace creates and disposes
  50.     private static final boolean verbose = false; // show reuse hits/misses
  51.     private static final boolean debug = false;   // show bad params, misc.
  52.  
  53.     public Graphics create() {
  54.         return createSwingGraphics(this);
  55.     }
  56.  
  57.     public Graphics create(int x,int y,int w,int h) {
  58.         if (debug && (w <= 0 || h <= 0)) {
  59.             System.out.println("bad size:  " + w + "x" + h);
  60.             Thread.dumpStack();
  61.         }
  62.         return createSwingGraphics(this, x, y, w, h);
  63.     }
  64.  
  65.     public Graphics subGraphics() {
  66.         Graphics g = graphics;
  67.  
  68.         /* We've handed our monitored object out, and can no longer track
  69.          * its state. */
  70.     restorable = false;
  71.  
  72.         return g;
  73.     }
  74.  
  75.     SwingGraphics(Graphics g) {
  76.         if(g == null) {
  77.             Thread.currentThread().dumpStack();
  78.         }
  79.         init(g);
  80.     }
  81.  
  82.     void init(Graphics g) {
  83.         if (g instanceof SwingGraphics) {
  84.             /* Clone an existing SwingGraphics object.  The dispose method
  85.              * must be called to reset the shared sub-graphics object to
  86.              * the same state it was in when cloned. */
  87.             SwingGraphics sg = (SwingGraphics)g;
  88.             originalGraphics = sg.originalGraphics;
  89.             graphics = sg.graphics;
  90.             previous = sg;
  91.             if (clipRect == null) {
  92.                 clipRect = new Rectangle(sg.clipRect.x, 
  93.                                          sg.clipRect.y, 
  94.                                          sg.clipRect.width, 
  95.                                          sg.clipRect.height);
  96.             } else {
  97.                 clipRect.x = sg.clipRect.x;
  98.                 clipRect.y = sg.clipRect.y;
  99.                 clipRect.width = sg.clipRect.width;
  100.                 clipRect.height = sg.clipRect.height;
  101.             }
  102.             currentColor = sg.currentColor;
  103.             currentFont = sg.currentFont;
  104.             if (verbose) {
  105.                 System.out.print('.');    // '.' means "cache" hit
  106.                 System.out.flush();
  107.             }
  108.         } else {
  109.             /* Initialize using a non-SwingGraphics Graphics object.  The 
  110.              * original object is cloned to prevent damage, and its initial
  111.              * state recorded. */
  112.             originalGraphics = g;
  113.             graphics = g.create();
  114.             previous = null;
  115.             Rectangle cr = g.getClipBounds();
  116.             if (cr == null) {
  117.                 if (clipRect == null) {
  118.                     // Not a recycled SwingGraphics, allocate Rectangle.
  119.                     clipRect = new Rectangle(0, 0, Integer.MAX_VALUE,
  120.                                              Integer.MAX_VALUE);
  121.                 } else {
  122.                     // Reuse recycled SwingGraphics' existing Rectangle.
  123.                     clipRect.x = clipRect.y = 0;
  124.                     clipRect.width = clipRect.height = Integer.MAX_VALUE;
  125.                 }
  126.             } else {
  127.                 // Save returned Rectangle.
  128.                 clipRect = cr;
  129.             }
  130.             currentColor = g.getColor();
  131.             currentFont = g.getFont();
  132.             if (verbose) {
  133.                 System.out.print('*');    // '.' means "cache" miss
  134.                 System.out.flush();
  135.             }
  136.         }
  137.     }
  138.  
  139.     public static Graphics createSwingGraphics(Graphics g) {
  140.         if (g == null) {
  141.             Thread.currentThread().dumpStack();
  142.             return null;
  143.         }
  144.  
  145.       
  146.         return g.create();
  147.         
  148.  
  149.  
  150.  
  151.  
  152.  
  153.  
  154.  
  155.  
  156.  
  157.  
  158.  
  159.  
  160.  
  161.  
  162.  
  163.  
  164.     }
  165.  
  166.     /**
  167.      * Create a SwingGraphics from another Graphics object, and set its clip
  168.      * to be the intersection of the first Graphics object's clip rect.
  169.      * Graphics.create() normally does this, but Microsoft's SDK for Java
  170.      * 2.0 doesn't set the clip of the returned object.  Since this method
  171.      * is supposed to emulate what Graphics.create() does, all potential
  172.      * bugs should be first checked with that method before changing the
  173.      * behavior here.
  174.      */
  175.     static Graphics createSwingGraphics(Graphics g, int x, int y,
  176.                                         int width, int height) {
  177.       
  178.         return g.create(x, y, width, height);
  179.         
  180.  
  181.  
  182.  
  183.  
  184.  
  185.  
  186.  
  187.  
  188.  
  189.  
  190.  
  191.  
  192.  
  193.  
  194.  
  195.  
  196.  
  197.  
  198.  
  199.  
  200.  
  201.  
  202.  
  203.  
  204.     }
  205.  
  206.     public void translate(int x,int y) {
  207.         graphics.translate(x,y);
  208.         translateX += x;
  209.         translateY += y;
  210.         clipRect.x -= x;
  211.         clipRect.y -= y;
  212.     }
  213.  
  214.     public Color getColor() {
  215.         return currentColor;
  216.     }
  217.  
  218.     public void setColor(Color c) {
  219.         graphics.setColor(c);
  220.         currentColor = c;
  221.     }
  222.  
  223.     public void setPaintMode() {
  224.         graphics.setPaintMode();
  225.  
  226.         /* There's no way to restore the original paint mode. */
  227.     restorable = false;
  228.     }
  229.  
  230.     public void setXORMode(Color c1) {
  231.         graphics.setXORMode(c1);
  232.  
  233.         /* There's no way to restore the original XOR mode. */
  234.     restorable = false;
  235.     }
  236.  
  237.     public Font getFont() {
  238.         return currentFont;
  239.     }
  240.  
  241.     public void setFont(Font font) {
  242.         graphics.setFont(font);
  243.         currentFont = font;
  244.     }
  245.  
  246.     public FontMetrics getFontMetrics() {
  247.     return graphics.getFontMetrics();
  248.     }
  249.  
  250.     public FontMetrics getFontMetrics(Font f) {
  251.         return graphics.getFontMetrics(f);
  252.     }
  253.  
  254.     public Rectangle getClipBounds() {
  255.         /* Clone rectangle since we can't return a const and don't want
  256.          * the caller to change this rectangle. */
  257.         return new Rectangle(clipRect);
  258.     }
  259.  
  260.     public boolean isClipIntersecting(Rectangle r) {
  261.         if (clipRect.x >= r.x + r.width || clipRect.x + clipRect.width <= r.x ||
  262.             clipRect.y >= r.y + r.height || clipRect.y + clipRect.height <= r.y) {
  263.             return false;
  264.         }
  265.         return !(clipRect.width == 0 || clipRect.height == 0 || r.width == 0 ||
  266.                  r.height == 0);
  267.     }
  268.  
  269.     public int getClipX() {
  270.         return clipRect.x;
  271.     }
  272.  
  273.     public int getClipY() {
  274.         return clipRect.y;
  275.     }
  276.  
  277.     public int getClipWidth() {
  278.         return clipRect.width;
  279.     }
  280.  
  281.     public int getClipHeight() {
  282.         return clipRect.height;
  283.     }
  284.  
  285.     public void clipRect(int x, int y, int width, int height) {
  286.         graphics.clipRect(x,y,width,height);
  287.         _changeClip(x, y, width, height, false);
  288.     }
  289.  
  290.     public void setClip(int x, int y, int width, int height) {
  291.         graphics.setClip(x,y,width,height);
  292.         _changeClip(x, y, width, height, true);
  293.     }
  294.  
  295.     public Shape getClip() {
  296.         return graphics.getClip();
  297.     }
  298.  
  299.     public void setClip(Shape clip) {
  300.         graphics.setClip(clip);
  301.         if(clip instanceof Rectangle) {
  302.             Rectangle r = (Rectangle) clip;
  303.             _changeClip(r.x,r.y,r.width,r.height,true);
  304.         }
  305.     }
  306.  
  307.     public void copyArea(int x, int y, int width, int height,
  308.                          int dx, int dy) {
  309.         if (debug && (width <= 0 || height <= 0)) {
  310.             System.out.println("bad size:  " + width + "x" + height);
  311.             Thread.dumpStack();
  312.         }
  313.  
  314.         graphics.copyArea(x,y,width,height,dx,dy);
  315.     }
  316.  
  317.     public void drawLine(int x1, int y1, int x2, int y2) {
  318.         graphics.drawLine(x1,y1,x2,y2);
  319.     }
  320.  
  321.     public void fillRect(int x, int y, int width, int height) {
  322.         if (debug && (width <= 0 || height <= 0)) {
  323.             System.out.println("bad size:  " + width + "x" + height);
  324.             Thread.dumpStack();
  325.         }
  326.  
  327.         graphics.fillRect(x,y,width,height);
  328.     }
  329.  
  330.     public void drawRect(int x, int y, int width, int height) {
  331.         if (debug && (width <= 0 || height <= 0)) {
  332.             System.out.println("bad size:  " + width + "x" + height);
  333.             Thread.dumpStack();
  334.         }
  335.  
  336.         graphics.drawRect(x, y, width, height);
  337.     }
  338.  
  339.     public void clearRect(int x, int y, int width, int height) {
  340.         if (debug && (width <= 0 || height <= 0)) {
  341.             System.out.println("bad size:  " + width + "x" + height);
  342.             Thread.dumpStack();
  343.         }
  344.  
  345.         graphics.clearRect(x,y,width,height);
  346.     }
  347.  
  348.     public void drawRoundRect(int x, int y, int width, int height,
  349.                               int arcWidth, int arcHeight) {
  350.         if (debug && (width <= 0 || height <= 0)) {
  351.             System.out.println("bad size:  " + width + "x" + height);
  352.             Thread.dumpStack();
  353.         }
  354.  
  355.         graphics.drawRoundRect(x,y,width,height,arcWidth,arcHeight);
  356.     }
  357.  
  358.     public void fillRoundRect(int x, int y, int width, int height,
  359.                               int arcWidth, int arcHeight) {
  360.         if (debug && (width <= 0 || height <= 0)) {
  361.             System.out.println("bad size:  " + width + "x" + height);
  362.             Thread.dumpStack();
  363.         }
  364.  
  365.         graphics.fillRoundRect(x,y,width,height,arcWidth,arcHeight);
  366.     }
  367.  
  368.     public void draw3DRect(int x, int y, int width, int height,
  369.                boolean raised) {
  370.     graphics.draw3DRect(x, y, width, height, raised);
  371.     }
  372.  
  373.     public void fill3DRect(int x, int y, int width, int height,
  374.                boolean raised) {
  375.     graphics.fill3DRect(x, y, width, height, raised);
  376.     }
  377.  
  378.     public void drawOval(int x, int y, int width, int height) {
  379.         if (debug && (width <= 0 || height <= 0)) {
  380.             System.out.println("bad size:  " + width + "x" + height);
  381.             Thread.dumpStack();
  382.         }
  383.  
  384.         graphics.drawOval(x,y,width,height);
  385.     }
  386.  
  387.     public void fillOval(int x, int y, int width, int height) {
  388.         if (debug && (width <= 0 || height <= 0)) {
  389.             System.out.println("bad size:  " + width + "x" + height);
  390.             Thread.dumpStack();
  391.         }
  392.  
  393.         graphics.fillOval(x,y,width,height);
  394.     }
  395.  
  396.     public void drawArc(int x, int y, int width, int height,
  397.                         int startAngle, int arcAngle) {
  398.         if (debug && (width <= 0 || height <= 0)) {
  399.             System.out.println("bad size:  " + width + "x" + height);
  400.             Thread.dumpStack();
  401.         }
  402.  
  403.         graphics.drawArc(x,y,width,height,startAngle,arcAngle);
  404.     }
  405.  
  406.     public void fillArc(int x, int y, int width, int height,
  407.                         int startAngle, int arcAngle) {
  408.         if (debug && (width <= 0 || height <= 0)) {
  409.             System.out.println("bad size:  " + width + "x" + height);
  410.             Thread.dumpStack();
  411.         }
  412.  
  413.         graphics.fillArc(x,y,width,height,startAngle,arcAngle);
  414.     }
  415.  
  416.     public void drawPolyline(int xPoints[], int yPoints[],
  417.                              int nPoints) {
  418.         graphics.drawPolyline(xPoints,yPoints,nPoints);
  419.     }
  420.  
  421.     public void drawPolygon(int xPoints[], int yPoints[],
  422.                             int nPoints) {
  423.         graphics.drawPolygon(xPoints,yPoints,nPoints);
  424.     }
  425.  
  426.     public void drawPolygon(Polygon p) {
  427.         graphics.drawPolygon(p);
  428.     }
  429.  
  430.     public void fillPolygon(int xPoints[], int yPoints[],
  431.                             int nPoints) {
  432.         graphics.fillPolygon(xPoints,yPoints,nPoints);
  433.     }
  434.  
  435.     public void fillPolygon(Polygon p) {
  436.         graphics.fillPolygon(p);
  437.     }
  438.  
  439.     public void drawString(String str, int x, int y) {
  440.         graphics.drawString(str,x,y);
  441.     }
  442.  
  443.     
  444.     public void drawString(AttributedCharacterIterator iterator, int x, int y) {
  445.         graphics.drawString(iterator,x,y);
  446.     }
  447.      
  448.  
  449.     public void drawChars(char data[], int offset, int length, int x, int y) {
  450.         graphics.drawChars(data, offset, length, x, y);
  451.     }
  452.  
  453.     public void drawBytes(byte data[], int offset, int length, int x, int y) {
  454.     graphics.drawBytes(data, offset, length, x, y);
  455.     }
  456.  
  457.     public boolean drawImage(Image img, int x, int y,
  458.                              ImageObserver observer) {
  459.         return graphics.drawImage(img,x,y,observer);
  460.     }
  461.  
  462.     public boolean drawImage(Image img, int x, int y,
  463.                              int width, int height,
  464.                              ImageObserver observer) {
  465.         if (debug && (width <= 0 || height <= 0)) {
  466.             System.out.println("bad size:  " + width + "x" + height);
  467.             Thread.dumpStack();
  468.         }
  469.  
  470.         return graphics.drawImage(img,x,y,width,height,observer);
  471.     }
  472.  
  473.     public boolean drawImage(Image img, int x, int y,
  474.                              Color bgcolor,
  475.                              ImageObserver observer) {
  476.         return graphics.drawImage(img,x,y,bgcolor,observer);
  477.     }
  478.  
  479.     public boolean drawImage(Image img, int x, int y,
  480.                              int width, int height,
  481.                              Color bgcolor,
  482.                              ImageObserver observer) {
  483.         if (debug && (width <= 0 || height <= 0)) {
  484.             System.out.println("bad size:  " + width + "x" + height);
  485.             Thread.dumpStack();
  486.         }
  487.  
  488.         return graphics.drawImage(img,x,y,width,height,bgcolor,observer);
  489.     }
  490.  
  491.     public boolean drawImage(Image img,
  492.                              int dx1, int dy1, int dx2, int dy2,
  493.                              int sx1, int sy1, int sx2, int sy2,
  494.                              ImageObserver observer) {
  495.         return graphics.drawImage(img,dx1,dy1,dx2,dy2,sx1,sy1,sx2,sy2,observer);
  496.     }
  497.  
  498.     public boolean drawImage(Image img,
  499.                              int dx1, int dy1, int dx2, int dy2,
  500.                              int sx1, int sy1, int sx2, int sy2,
  501.                              Color bgcolor,
  502.                              ImageObserver observer) {
  503.         return graphics.drawImage(img,dx1,dy1,dx2,dy2,sx1,sy1,sx2,sy2,bgcolor,observer);
  504.     }
  505.  
  506.     /* Restore the shared sub-graphics object to its original state. */
  507.     private void resetGraphics() {
  508.         if (trace) {
  509.             System.out.println("resetGraphics: 0x" + 
  510.                                Integer.toHexString(hashCode()));
  511.         }
  512.     if (restorable) {
  513.         restoreGraphics();
  514.     } else {
  515.         replaceGraphics();
  516.     }
  517.     }
  518.  
  519.     /* The shared sub-graphics object can be restored to the previous
  520.      * state of this object, so do so.
  521.      */
  522.     private void restoreGraphics() {
  523.         if (currentFont != previous.currentFont) {
  524.             setFont(previous.currentFont);
  525.         }
  526.         if (currentColor != previous.currentColor) {
  527.             setColor(previous.currentColor);
  528.         }
  529.         if (translateX != 0 || translateY != 0) {
  530.             translate(-translateX, -translateY);
  531.         }
  532.         if (clipRect.x != previous.clipRect.x || 
  533.             clipRect.y != previous.clipRect.y ||
  534.             clipRect.width != previous.clipRect.width || 
  535.             clipRect.height != previous.clipRect.height) {
  536.             setClip(previous.clipRect.x, previous.clipRect.y,
  537.                     previous.clipRect.width, previous.clipRect.height);
  538.         }
  539.     }
  540.  
  541.     /* The shared sub-graphics object has been modified in an unrestorable
  542.      * way, so re-create one and substitute the new one for the clobbered
  543.      * one in our stack.  This is an expensive operation.
  544.      */
  545.     private void replaceGraphics() {
  546.         if (trace || debug) {
  547.             System.out.println("replaceGraphics: 0x" + 
  548.                                Integer.toHexString(hashCode()));
  549.         }
  550.         graphics = originalGraphics.create();
  551.         redoTranslate();
  552.         graphics.setColor(currentColor);
  553.         graphics.setFont(currentFont);
  554.         graphics.setClip(clipRect.x, clipRect.y, clipRect.width, clipRect.height);
  555.     }
  556.  
  557.     /* Reapply any translate operation.  This method is recursive so
  558.      * that the multiple translates are applied in in the same order
  559.      * as the SwingGraphics stack.
  560.      */
  561.     private void redoTranslate() {
  562.         if (previous != null) {
  563.             previous.redoTranslate();
  564.         }
  565.         if (translateX != 0 || translateY != 0) {
  566.             graphics.translate(translateX, translateY);
  567.         }
  568.     }
  569.  
  570.     public void dispose() {
  571.         if (trace) {
  572.             System.out.println(
  573.                 "dispose: 0x" + Integer.toHexString(hashCode()) + 
  574.                 "(" + (previous == null ? "null" : 
  575.                        Integer.toHexString(previous.hashCode())) + ")");
  576.         }
  577.         if (graphics != null) {
  578.             if (previous != null) {
  579.                 // In stack - do a graphics state "pop".
  580.                 resetGraphics();
  581.             } else {
  582.                 // Bottom of stack, truly dispose of the wrapped object.
  583.                 graphics.dispose();
  584.             }
  585.         }
  586.         graphics = null;
  587.         SwingGraphics.recycleSwingGraphics(this);
  588.     }
  589.  
  590.     public void finalize() {
  591.     graphics.finalize();
  592.     }
  593.  
  594.     public String toString() {
  595.         String fontString = currentFont.toString();
  596.         fontString = fontString.substring(fontString.indexOf('['));
  597.     return "SwingGraphics(0x" + Integer.toHexString(hashCode()) + 
  598.             ") [subGraphics " + 
  599.             originalGraphics.getClass().getName() + 
  600.             "\n   translate [x=" + translateX + ",y=" + translateY +
  601.             "] clip [x=" + clipRect.x + ",y=" + clipRect.y +
  602.             ",w=" + clipRect.width + ",h=" + clipRect.height +
  603.             "]\n   color [r=" + currentColor.getRed() + 
  604.             ",g=" + currentColor.getGreen() + 
  605.             ",b=" + currentColor.getBlue() + 
  606.             "] font " + fontString + "]";
  607.     }
  608.  
  609.     public Rectangle getClipRect() {
  610.     return graphics.getClipRect();
  611.     }
  612.  
  613.     private void _changeClip(int x,int y,int w,int h,boolean set) {
  614.         if(set) {
  615.             clipRect.x = x;
  616.             clipRect.y = y;
  617.             clipRect.width = w;
  618.             clipRect.height = h;
  619.         } else {
  620.             SwingUtilities.computeIntersection(x,y,w,h,clipRect);
  621.         }
  622.     }
  623.  
  624.     private static Stack pool = new Stack();
  625.  
  626.     private static synchronized void recycleSwingGraphics(SwingGraphics g) {
  627.         if (debug) {
  628.             if (pool.indexOf(g) != -1) {
  629.                 System.out.println("Tried to recycle the same graphics twice!");
  630.                 Thread.dumpStack();
  631.             }
  632.         }
  633.         pool.push(g);
  634.     }
  635.  
  636.     private static synchronized SwingGraphics getRecycledSwingGraphics() {
  637.         SwingGraphics r = null;
  638.         if (pool.size() > 0) {
  639.             r = (SwingGraphics) pool.pop();
  640.         }
  641.         return r;
  642.     }
  643.  
  644.     static {
  645.         // Warn if running wrong version of this class for this JDK.
  646.         
  647.           if (!SwingUtilities.is1dot2) {
  648.               System.err.println("warning: running 1.2 version of SwingGraphics");
  649.           }
  650.           
  651.  
  652.  
  653.  
  654.  
  655.  
  656.  
  657.  
  658.  
  659.     }
  660. }
  661.